package com.bkck.sharkblockade.levels.thread;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.bkck.sharkblockade.fish.Fish;
import com.bkck.sharkblockade.highscores.ScoresDB;
import com.bkck.sharkblockade.jellyfish.Jellyfish;
import com.bkck.sharkblockade.levels.LevelSelection;
import com.bkck.sharkblockade.levels.ball.Ball;
import com.bkck.sharkblockade.levels.block.Block;
import com.bkck.sharkblockade.levels.explosion.Explosion;
import com.bkck.sharkblockade.levels.harpoon.Harpoon;
import com.bkck.sharkblockade.levels.item.Item;
import com.bkck.sharkblockade.levels.block.BlockEdges;
import com.bkck.sharkblockade.levels.lines.Line;
import com.bkck.sharkblockade.levels.paddle.Paddle;
import com.bkck.sharkblockade.levels.shark.EatBall;
import com.bkck.sharkblockade.levels.shark.Shark;
import com.bkck.sharkblockade.levels.shark.SharkDeath;
import com.bkck.sharkblockade.loadPage.LoadingPage;
import com.bkck.sharkblockade.menu.R;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

/**
 * The main surface that handles the ontouch events and draws the image to the screen.
 * 
 * @author Team BKCK
 * 
 */
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback {

  public static final String TAG = MainGamePanel.class.getSimpleName();

  // constants used for creating blocks
  public static final int PIXELS_BETWEEN_BLOCKS = 3;
  public static final int NUM_BLOCKS_HORIZONTAL = 7;
  public static final int NUM_BLOCKS_VERTICAL = 5;
  public static int TOP_ROW = 0;
  public static int BOTTOM_ROW = 0;
  public static int LEFT_COLUMN = 0;
  public static int RIGHT_COLUMN = 0;

  // speed and position of the sharks
  public static int BLUE_SHARK_HEIGHT = 0;
  private static int BLUE_SHARK_VELOCITY = -10;
  public static int ORANGE_SHARK_HEIGHT = 0;
  private static int ORANGE_SHARK_VELOCITY = 10;

  public static int viewWidth;
  public static int viewHeight;

  // the level this SurfaceView is for.
  private static int level;
  // number of sharks to create in this level.
  private static int sharks;
  // number of jellyfish to create in this level.
  private static int jellyfish;
  // number of fish to create in this level.
  private static int fish;

  private static long blueSharkKilledAt = -1;
  private static long orangeSharkKilledAt = -1;
  private long pausedTime = -1;

  private static MainThread thread;

  // all the objects contained for this level.
  private Paddle paddle;
  private Ball ball;
  private List<Block> blocks = new ArrayList<Block>();

  private BlockEdges blockEdges = new BlockEdges();

  private HashMap<Line, Block> blockEdgesMap = new HashMap<Line, Block>();

  private Item item;
  private Harpoon harpoon;
  private Shark blueShark = null;
  private Shark orangeShark = null;
  private Jellyfish jellyfish1;
  private Jellyfish jellyfish2;
  private Jellyfish jellyfish3;
  private Jellyfish jellyfish4;
  private Jellyfish jellyfish5;
  private List<Jellyfish> jellyfishList = new ArrayList<Jellyfish>(5);
  private Fish fish1;
  private Fish fish2;
  private List<Fish> fishList = new ArrayList<Fish>(2);

  private Explosion explosion;
  private Bitmap[] explosionImages;

  private EatBall orangeEatBall;
  private EatBall blueEatBall;
  private Bitmap[] blueEatingImages;
  private Bitmap[] orangeEatingImages;

  private SharkDeath blueSharkDying;
  private Bitmap[] blueDyingImages;
  private SharkDeath orangeSharkDying;
  private Bitmap[] orangeDyingImages;

  // Sound pool which allows us to play multiple sounds at once.
  private static SoundPool soundPool;

  // id of the sounds
  private static int explosionSound = 0;
  private static int blockHitSound = 1;
  private static int paddleHitSound = 2;

  public static Bitmap paddleStunned;

  private static boolean soundLoaded = false;

  // all the images needed for this level.
  public static Bitmap background;
  public static Bitmap redBlock;
  public static Bitmap yellowBlock;
  public static Bitmap greenBlock;
  public static Bitmap blackBlock;
  public static Bitmap grayBlock;
  public static Bitmap ballBitmap;
  public static Bitmap smallPaddle;
  public static Bitmap mediumPaddle;
  public static Bitmap largePaddle;
  public static Bitmap unknownItem;
  public static Bitmap blueSharkBitmap;
  public static Bitmap orangeSharkBitmap;
  public static Bitmap harpoonBitmap;
  public static Bitmap spikedBallBitmap;
  public static Bitmap ghostBallBitmap;
  public static Bitmap blank;
  public static Bitmap jellyfishBitmap;
  public static Bitmap fishBitmap;

  public static Bitmap greenClock;
  public static Bitmap redClock;
  public static Bitmap blueClock;
  public static Bitmap orangeClock;
  // public static Bitmap greenMusubi;
  // public static Bitmap redMusubi;
  public static Bitmap paddleIncrease;
  public static Bitmap paddleDecrease;
  public static Bitmap harpoonItem;
  public static Bitmap spikedItem;
  public static Bitmap ghostItem;
  public static Bitmap bombItem;

  public static Bitmap greenClockIcon;
  public static Bitmap redClockIcon;
  public static Bitmap blueClockIcon;
  public static Bitmap orangeClockIcon;
  // public static Bitmap greenMusubiIcon;
  // public static Bitmap redMusubiIcon;
  public static Bitmap paddleIncreaseIcon;
  public static Bitmap paddleDecreaseIcon;
  public static Bitmap harpoonIcon;
  public static Bitmap spikedBallIcon;
  public static Bitmap ghostBallIcon;
  public static Bitmap bombIcon;

  public static Bitmap explosion01;
  public static Bitmap explosion02;
  public static Bitmap explosion03;
  public static Bitmap explosion04;

  public static Bitmap orangeSharkEating00;
  public static Bitmap orangeSharkEating01;
  public static Bitmap orangeSharkEating02;
  public static Bitmap orangeSharkEating03;
  public static Bitmap orangeSharkEating04;
  public static Bitmap orangeSharkEating05;
  public static Bitmap orangeSharkEating06;
  public static Bitmap orangeSharkEating07;
  public static Bitmap orangeSharkEating08;
  public static Bitmap blueSharkEating00;
  public static Bitmap blueSharkEating01;
  public static Bitmap blueSharkEating02;
  public static Bitmap blueSharkEating03;
  public static Bitmap blueSharkEating04;
  public static Bitmap blueSharkEating05;
  public static Bitmap blueSharkEating06;
  public static Bitmap blueSharkEating07;
  public static Bitmap blueSharkEating08;

  public static Bitmap blueSharkDying00;
  public static Bitmap blueSharkDying01;
  public static Bitmap blueSharkDying02;
  public static Bitmap blueSharkDying03;
  public static Bitmap blueSharkDying04;
  public static Bitmap blueSharkDying05;
  public static Bitmap blueSharkDying06;
  public static Bitmap orangeSharkDying00;
  public static Bitmap orangeSharkDying01;
  public static Bitmap orangeSharkDying02;
  public static Bitmap orangeSharkDying03;
  public static Bitmap orangeSharkDying04;
  public static Bitmap orangeSharkDying05;
  public static Bitmap orangeSharkDying06;

  public static Bitmap questionMark;

  private static boolean imagesLoaded = false;

  private boolean goToNextLevel;

  SharedPreferences preferences;
  EditText usernameInput;

  private Paint paint = new Paint();

  /**
   * This constructor is invoked when we include this custom view in a layout.xml.
   * 
   * @param context
   * @param attributeset
   */
  public MainGamePanel(Context context, AttributeSet attributeset) {

    // need to pass attribute set to make this custom view work in the layout
    super(context, attributeset);
    // adding the callback to the surface holder to intercept events
    getHolder().addCallback(this);

    if (!imagesLoaded) {
      Log.d(TAG, "Loading images..");
      loadImageResources();
      imagesLoaded = true;
    }

    if (!soundLoaded) {
      Log.d(TAG, "Loading sound effects..");
      loadSoundResources();
      soundLoaded = true;
    }

    // create the game loop thread
    thread = new MainThread(getHolder(), this);

    // make the GamePanel focusable so it can handle events
    setFocusable(true);
    setFocusableInTouchMode(true);
    requestFocus();

    goToNextLevel = false;

    Log.d(TAG, "Constructed MainGamePanel");
  }

  /**
   * Initialize objects for this level.
   * 
   * @param sharks
   * @param level
   */
  public void initializeObjects(int sharks, int level, int jellyfish, int fish) {
    MainGamePanel.level = level;
    MainGamePanel.sharks = sharks;
    MainGamePanel.jellyfish = jellyfish;
    MainGamePanel.fish = fish;
  }

  /**
   * Invoked when this surface is changed.
   */
  public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    Log.d(TAG, "In surfaceChanged");
  }

  /**
   * Invoked when this surface is created and starts the thread.
   */
  public void surfaceCreated(SurfaceHolder arg0) {
    Log.d(TAG, "In surfaceCreated");
    viewWidth = getWidth();
    viewHeight = getHeight();

    // the changes needed to fit different screen sizes.
    resizeImages();

    createPaddle();
    createBall();
    createItem();
    createHarpoon();
    createExplosion();
    createEatBall();
    createSharkDeath();

    // different screen sizes will result in different margins
    adjustBlockLocation();

    int[] levelBlockRows;
    int[] levelBlockColumns;
    int[] levelBlockColors;

    if (level == 1) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 2) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 2, 1, 2, 1, 2, 1, 2, 1, -1, 1, 1, 1, -1, 1, 2, -1, 3, 3, 3, -1, 2, 1, -1, -1,
              -1, -1, -1, 1, 2, 1, 2, 1, 2, 1, 2 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 3) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 3, 3, 3, 2, 3, 3, 3, 3, 2, 2, 1, 2, 2, 3, 2, 2, 1, 1, 1, 2, 2, 3, 2, 2, 1, 2,
              2, 3, 3, 3, 3, 2, 3, 3, 3 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 4) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 1, -1, -1, -2, -1, -1, 1, -1, 3, 3, 3, 3, 3, -1, -2, 3, 3, 3, 3, 3, -2, -1,
              3, 3, 3, 3, 3, -1, 1, -1, -1, -2, -1, -1, 1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 5) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { -1, -1, -1, 3, -1, -1, -1, -1, 3, -1, 3, -1, 3, -1, -1, 3, -1, 3, -1, 3, -1,
              -1, 3, 3, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }

    // change the locations of sharks according to the distance between the blocks and the paddle.
    adjustSharkLocation();
    createSharks(sharks);
    createJellyfish();
    createFish();

    Log.d(TAG, "View Width: " + this.getWidth());
    Log.d(TAG, "View Height: " + this.getHeight());
    Log.d(TAG, "Block Width: " + greenBlock.getWidth());
    Log.d(TAG, "Block Height: " + greenBlock.getHeight());
    Log.d(TAG, "Top Gap: " + TOP_ROW);
    Log.d(TAG, "Left Column: " + LEFT_COLUMN);
    thread.setStartTime(System.currentTimeMillis());
    thread.setRunning(true);
    thread.start();

  }

  /**
   * Scale up or down the image sizes according to the screen size.
   */
  public void resizeImages() {
    // right now only doing it for the background
    background = Bitmap.createScaledBitmap(background, getWidth(), getHeight(), true);
  }

  /**
   * Calculate for the proper locations for blocks.
   */
  public void adjustBlockLocation() {
    TOP_ROW = 2 * greenBlock.getHeight() + 2 * PIXELS_BETWEEN_BLOCKS + ((2 * viewHeight) / 425);
    BOTTOM_ROW = TOP_ROW + 6 * PIXELS_BETWEEN_BLOCKS + 7 * redBlock.getHeight();
    int added = greenBlock.getWidth() + PIXELS_BETWEEN_BLOCKS + (getWidth() / 80);
    LEFT_COLUMN = added;
    RIGHT_COLUMN = getWidth() - added;
  }

  /**
   * Calculate for the proper locations for sharks.
   */
  public void adjustSharkLocation() {
    if (sharks > 0) {
      float lastRowY =
          blocks.get(blocks.size() - 1).getHeight() + blocks.get(blocks.size() - 1).getY();
      BLUE_SHARK_HEIGHT = (int) (lastRowY + (paddle.getY() - lastRowY) / 3);
      if (sharks == 2) {
        ORANGE_SHARK_HEIGHT = (int) (lastRowY + (paddle.getY() - lastRowY) / 3 * 2);
      }
    }
  }

  /**
   * Invoked when this surface is destroyed. This method ensures a clean thread shut down.
   */
  public void surfaceDestroyed(SurfaceHolder arg0) {

    boolean retry = true;
    while (retry) {
      try {
        // wait for the main thread to shut down
        thread.join();
        retry = false;
      }
      catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    Log.d(TAG, "Thread was shut down cleanly");
  }

  /**
   * update any condition in the game.
   */
  public void update() {

    item.update(paddle, ball, harpoon, blueShark, orangeShark, fishList, blockEdges);

    if (harpoon.getLaunched()) {
      harpoon.updatePosition(blueShark, orangeShark, blueSharkDying, orangeSharkDying);
    }
    if (sharks == 1) {
      blueShark.updatePosition(ball, blueEatBall);
    }
    if (sharks == 2) {
      blueShark.updatePosition(ball, blueEatBall);
      orangeShark.updatePosition(ball, orangeEatBall);
    }

    for (Jellyfish jelly : jellyfishList) {
      jelly.updatePosition(paddle);
    }

    for (Fish fish : fishList) {
      fish.updatePosition(ball);
    }

    explosion.update();
    blueEatBall.update(ball);
    orangeEatBall.update(ball);
    blueSharkDying.update();
    orangeSharkDying.update();
    ball.update(paddle, blocks, item, harpoon, explosion, blockEdgesMap, blockEdges);
  }

  /**
   * Render the whole page again after each update.
   * 
   * @param canvas
   */
  protected void render(Canvas canvas) {
    // redraw background..if it's an image we can do drawBitmap(..)
    // have to redraw the whole background again so we don't see trails
    // for the moving images.
    canvas.drawBitmap(background, 0, 0, null);
    // canvas.drawColor(Color.BLACK);
    paddle.draw(canvas);
    ball.draw(canvas);
    drawBlocks(canvas);
    if (item.isVisible() && item.getType() != null) {
      item.draw(canvas);
    }
    if (harpoon.getLaunched()) {
      harpoon.draw(canvas);
    }
    if (sharks == 1) {
      blueShark.draw(canvas);

      if (blueShark.isConfused()) {
        canvas.drawBitmap(questionMark, blueShark.getX(),
            blueShark.getY() - questionMark.getHeight(), null);
      }
    }
    if (sharks == 2) {
      blueShark.draw(canvas);

      if (blueShark.isConfused()) {
        canvas.drawBitmap(questionMark, blueShark.getX(),
            blueShark.getY() - questionMark.getHeight(), null);
      }

      orangeShark.draw(canvas);

      if (orangeShark.isConfused()) {
        canvas.drawBitmap(questionMark, orangeShark.getX() + orangeShark.getWidth() / 2,
            orangeShark.getY() - questionMark.getHeight(), null);
      }
    }

    for (Jellyfish jelly : jellyfishList) {
      jelly.draw(canvas);
    }

    for (Fish fish : fishList) {
      fish.draw(canvas);
    }

    if (item.getTimeRemaining() > 0 && item.getType() != null) {
      drawIcon(canvas);
      drawIconLine(canvas);
    }

    explosion.draw(canvas);
    if (blueEatBall.getEating()) {
      blueEatBall.draw(canvas);
    }
    else if (orangeEatBall.getEating()) {
      orangeEatBall.draw(canvas);
    }

    if (blueSharkDying.isDying()) {
      blueSharkDying.draw(canvas);
    }
    if (orangeSharkDying.isDying()) {
      orangeSharkDying.draw(canvas);
    }
  }

  /**
   * Draw the power up icon when it's in effect.
   * 
   * @param canvas The canvas.
   */
  public void drawIcon(Canvas canvas) {
    // draw icon for fast ball
    if (item.getType() == Item.FASTER_BALL) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(redClockIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(redClockIcon, 2, 2, null);
      }
    }
    // draw icon for slower ball
    if (item.getType() == Item.SLOWER_BALL) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(greenClockIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(greenClockIcon, 2, 2, null);
      }
    }
    // draw icon for larger paddle
    if (item.getType() == Item.LARGER_PADDLE) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(paddleIncreaseIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(paddleIncreaseIcon, 2, 2, null);
      }
    }
    // draw icon for smaller paddle
    if (item.getType() == Item.SMALLER_PADDLE) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(paddleDecreaseIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(paddleDecreaseIcon, 2, 2, null);
      }
    }
    // draw icon for faster shark
    if (item.getType() == Item.FASTER_SHARK) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(orangeClockIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(orangeClockIcon, 2, 2, null);
      }
    }
    // draw icon for slower shark
    if (item.getType() == Item.SLOWER_SHARK) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(blueClockIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(blueClockIcon, 2, 2, null);
      }
    }
    // draw icon for harpoon
    if (item.getType() == Item.HARPOON) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(harpoonIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(harpoonIcon, 2, 2, null);
      }
    }
    // draw icon for spiked ball
    if (item.getType() == Item.SPIKED_BALL) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(spikedBallIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(spikedBallIcon, 2, 2, null);
      }
    }
    // draw icon for spiked ball
    if (item.getType() == Item.GHOST_BALL) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
          canvas.drawBitmap(ghostBallIcon, 2, 2, null);
        }
      }
      else {
        canvas.drawBitmap(ghostBallIcon, 2, 2, null);
      }
    }
    // draw icon for bomb
    if (item.getType() == Item.BOMB) {
      if (item.getTimeRemaining() <= 5000) {
        if (thread.getTimeElapsed() % 1000 >= 500) {
    	  canvas.drawBitmap(bombIcon, 2, 2, null);	
    	}
      }
      else {
    	canvas.drawBitmap(bombIcon, 2, 2, null);
      }
    }

  }

  /**
   * Draw the line that represents the time remaining for an item.
   * 
   * @param canvas
   */
  public void drawIconLine(Canvas canvas) {
    if (item.getTimeRemaining() > 10000) {
      paint.setColor(Color.GREEN);
    }
    else if (item.getTimeRemaining() > 5000) {
      paint.setColor(Color.YELLOW);
    }
    else {
      paint.setColor(Color.RED);
    }
    canvas.drawLine(25, 10, item.getTimeRemaining() / 200 + 25, 10, paint);
    canvas.drawLine(25, 11, item.getTimeRemaining() / 200 + 25, 11, paint);

  }

  /**
   * Draw the list of blocks and calculate the total blocks left to destroy.
   * 
   * @param blocks
   * @param canvas
   */
  public void drawBlocks(Canvas canvas) {
    int blocksLeft = 0;
    for (Block block : blocks) {
      if (block.getColor() == Block.RED) {
        block.setBitmap(redBlock);
        blocksLeft++;
      }
      if (block.getColor() == Block.YELLOW) {
        block.setBitmap(yellowBlock);
        blocksLeft++;
      }
      if (block.getColor() == Block.GREEN) {
        block.setBitmap(greenBlock);
        blocksLeft++;
      }
      if (block.getColor() == Block.BLACK) {
        blocksLeft++;
      }
      block.draw(canvas);
    }
    Block.blocksToBreak = blocksLeft;
  }

  /**
   * Handles the interaction between the player and our custom view
   */
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      // move paddle to where the finger is if (x,y) is below the paddle
      paddle.handleActionDown((int) event.getX(), (int) event.getY(), getWidth());
      // if the item contains the point (x,y), the power up is obtained upon touch
      item.handleActionDown((int) event.getX(), (int) event.getY(), paddle, ball, harpoon,
          blueShark, orangeShark);
    }

    // let the paddle follow the sliding finger
    if (event.getAction() == MotionEvent.ACTION_MOVE) {
      if (!paddle.getStunned()) {
        if (paddle.isTouched()) {
          if (event.getX() > paddle.getBitmap().getWidth() / 2
              && event.getX() < getWidth() - paddle.getBitmap().getWidth() / 2)
            paddle.setX((int) event.getX() - paddle.getBitmap().getWidth() / 2);
        }
      }
    }
    if (event.getAction() == MotionEvent.ACTION_UP) {

      // if the ball is resting on top of the paddle, launch it.
      if (!ball.isLaunched() && paddle.isTouched() && !ball.isEaten()) {

        // divide the screen up to 3 portions, the ball will be release in
        // different directions depending on whether the paddle is close to left, middle, or right
        // side of the screen.
        if (event.getX() < getWidth() / 2 - paddle.getWidth() / 2) {
          ball.setXVelocity(-3);
        }
        else if (event.getX() > getWidth() / 2 + paddle.getWidth() / 2) {
          ball.setXVelocity(3);
        }
        // width of middle portion is the smallest (equals the width of the paddle)
        else {
          ball.setXVelocity(0);
        }
        ball.launch();
      }

      // releases the paddle
      if (paddle.isTouched()) {
        paddle.setTouched(false);
      }
      // shoot harpoon if we have it
      if ((int) event.getY() >= paddle.getY()) {
        if (harpoon.powerupObtained()) {
          harpoon.appear(paddle);
          item.setTimeRemaining(-1);
        }
      }
    }
    return true;
  }

  /**
   * To be accessed by each level when the player exits the level.
   */
  public void shutdownThread() {
    pausedTime = System.currentTimeMillis();
    for (Fish fish : fishList) {
      fish.pause();
    }

    for (Jellyfish jelly : jellyfishList) {
      jelly.pause();
    }

    thread.setRunning(false);
  }

  /**
   * Load the sound effects for this level.
   */
  public void loadSoundResources() {
    soundPool = new SoundPool(16, AudioManager.STREAM_MUSIC, 100);
    explosionSound = soundPool.load(getContext(), R.raw.explosion, 0);
    blockHitSound = soundPool.load(getContext(), R.raw.blockdestroyed, 0);
    paddleHitSound = soundPool.load(getContext(), R.raw.paddle_collision, 0);
  }

  /**
   * Load the images for this level.
   */
  public void loadImageResources() {

    background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
    smallPaddle = BitmapFactory.decodeResource(getResources(), R.drawable.small_paddle);
    mediumPaddle = BitmapFactory.decodeResource(getResources(), R.drawable.paddle);
    paddleStunned = BitmapFactory.decodeResource(getResources(), R.drawable.paddle_hit);
    largePaddle = BitmapFactory.decodeResource(getResources(), R.drawable.large_paddle);
    ballBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
    redBlock = BitmapFactory.decodeResource(getResources(), R.drawable.redblock);
    yellowBlock = BitmapFactory.decodeResource(getResources(), R.drawable.yellowblock);
    blackBlock = BitmapFactory.decodeResource(getResources(), R.drawable.bombblock);
    greenBlock = BitmapFactory.decodeResource(getResources(), R.drawable.greenblock);
    grayBlock = BitmapFactory.decodeResource(getResources(), R.drawable.grayblock);
    unknownItem = BitmapFactory.decodeResource(getResources(), R.drawable.unknown);
    blueSharkBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_left);
    orangeSharkBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_right);
    harpoonBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.harpoon);
    spikedBallBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.spiked_ball);
    ghostBallBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ghost_ball);
    blank = BitmapFactory.decodeResource(getResources(), R.drawable.blank);
    jellyfishBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.jellyfish);
    fishBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fish);

    greenClock = BitmapFactory.decodeResource(getResources(), R.drawable.green_clock);
    redClock = BitmapFactory.decodeResource(getResources(), R.drawable.red_clock);
    blueClock = BitmapFactory.decodeResource(getResources(), R.drawable.blue_clock);
    orangeClock = BitmapFactory.decodeResource(getResources(), R.drawable.orange_clock);
    // greenMusubi = BitmapFactory.decodeResource(getResources(), R.drawable.green_musubi);
    // redMusubi = BitmapFactory.decodeResource(getResources(), R.drawable.red_musubi);
    paddleIncrease = BitmapFactory.decodeResource(getResources(), R.drawable.paddle_increase);
    paddleDecrease = BitmapFactory.decodeResource(getResources(), R.drawable.paddle_decrease);
    harpoonItem = BitmapFactory.decodeResource(getResources(), R.drawable.harpoon_item);
    spikedItem = BitmapFactory.decodeResource(getResources(), R.drawable.spiked);
    ghostItem = BitmapFactory.decodeResource(getResources(), R.drawable.ghost);
    bombItem = BitmapFactory.decodeResource(getResources(), R.drawable.bomb_item);

    greenClockIcon = BitmapFactory.decodeResource(getResources(), R.drawable.green_clock_icon);
    redClockIcon = BitmapFactory.decodeResource(getResources(), R.drawable.red_clock_icon);
    blueClockIcon = BitmapFactory.decodeResource(getResources(), R.drawable.blue_clock_icon);
    orangeClockIcon = BitmapFactory.decodeResource(getResources(), R.drawable.orange_clock_icon);
    // greenMusubiIcon = BitmapFactory.decodeResource(getResources(), R.drawable.green_musubi_icon);
    // redMusubiIcon = BitmapFactory.decodeResource(getResources(), R.drawable.red_musubi_icon);
    paddleIncreaseIcon =
        BitmapFactory.decodeResource(getResources(), R.drawable.paddle_increase_icon);
    paddleDecreaseIcon =
        BitmapFactory.decodeResource(getResources(), R.drawable.paddle_decrease_icon);
    harpoonIcon = BitmapFactory.decodeResource(getResources(), R.drawable.harpoon_icon);
    spikedBallIcon = BitmapFactory.decodeResource(getResources(), R.drawable.spiked_icon);
    ghostBallIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ghost_icon);
    bombIcon = BitmapFactory.decodeResource(getResources(), R.drawable.bomb_icon);

    explosion01 = BitmapFactory.decodeResource(getResources(), R.drawable.bombblock_explosion_01);
    explosion02 = BitmapFactory.decodeResource(getResources(), R.drawable.bombblock_explosion_02);
    explosion03 = BitmapFactory.decodeResource(getResources(), R.drawable.bombblock_explosion_03);
    explosion04 = BitmapFactory.decodeResource(getResources(), R.drawable.bombblock_explosion_04);

    orangeSharkEating00 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_00);
    orangeSharkEating01 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_01);
    orangeSharkEating02 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_02);
    orangeSharkEating03 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_03);
    orangeSharkEating04 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_04);
    orangeSharkEating05 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_05);
    orangeSharkEating06 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_06);
    orangeSharkEating07 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_07);
    orangeSharkEating08 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_eating_ball_08);
    blueSharkEating00 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_00);
    blueSharkEating01 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_01);
    blueSharkEating02 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_02);
    blueSharkEating03 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_03);
    blueSharkEating04 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_04);
    blueSharkEating05 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_05);
    blueSharkEating06 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_06);
    blueSharkEating07 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_07);
    blueSharkEating08 =
        BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_eating_ball_08);

    blueSharkDying00 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_00);
    blueSharkDying01 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_01);
    blueSharkDying02 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_02);
    blueSharkDying03 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_03);
    blueSharkDying04 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_04);
    blueSharkDying05 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_05);
    blueSharkDying06 = BitmapFactory.decodeResource(getResources(), R.drawable.blue_shark_dying_06);
    orangeSharkDying00 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_00);
    orangeSharkDying01 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_01);
    orangeSharkDying02 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_02);
    orangeSharkDying03 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_03);
    orangeSharkDying04 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_04);
    orangeSharkDying05 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_05);
    orangeSharkDying06 =
        BitmapFactory.decodeResource(getResources(), R.drawable.orange_shark_dying_06);

    questionMark = BitmapFactory.decodeResource(getResources(), R.drawable.question_mark);

  }

  /**
   * Play the explosion sound.
   */
  public static void playExplosionSound() {
    // soundPool.play(explosionSound, 1, 1, 0, 0, 1);
  }

  /**
   * Play the sound when the ball collides with the paddle.
   */
  public static void playPaddleHitSound() {
    // soundPool.play(paddleHitSound, 1, 1, 0, 0, 1);
  }

  /**
   * Play the sound when a block is destroyed.
   */
  public static void playBlockHitSound() {
    // soundPool.play(blockHitSound, 1, 1, 0, 0, 1);
  }

  /**
   * Initialize the explosion object.
   */
  public void createExplosion() {
    explosionImages = new Bitmap[4];
    explosionImages[0] = explosion01;
    explosionImages[1] = explosion02;
    explosionImages[2] = explosion03;
    explosionImages[3] = explosion04;

    explosion = new Explosion(explosionImages);
  }

  /**
   * Initialize the EatBall object.
   */
  public void createEatBall() {
    orangeEatingImages = new Bitmap[9];
    orangeEatingImages[0] = orangeSharkEating00;
    orangeEatingImages[1] = orangeSharkEating01;
    orangeEatingImages[2] = orangeSharkEating02;
    orangeEatingImages[3] = orangeSharkEating03;
    orangeEatingImages[4] = orangeSharkEating04;
    orangeEatingImages[5] = orangeSharkEating05;
    orangeEatingImages[6] = orangeSharkEating06;
    orangeEatingImages[7] = orangeSharkEating07;
    orangeEatingImages[8] = orangeSharkEating08;

    orangeEatBall = new EatBall(orangeEatingImages);

    blueEatingImages = new Bitmap[9];

    blueEatingImages[0] = blueSharkEating00;
    blueEatingImages[1] = blueSharkEating01;
    blueEatingImages[2] = blueSharkEating02;
    blueEatingImages[3] = blueSharkEating03;
    blueEatingImages[4] = blueSharkEating04;
    blueEatingImages[5] = blueSharkEating05;
    blueEatingImages[6] = blueSharkEating06;
    blueEatingImages[7] = blueSharkEating07;
    blueEatingImages[8] = blueSharkEating08;

    blueEatBall = new EatBall(blueEatingImages);
  }

  /**
   * Initialize the SharkDeath object(s).
   */

  public void createSharkDeath() {
    blueDyingImages = new Bitmap[7];
    blueDyingImages[0] = blueSharkDying00;
    blueDyingImages[1] = blueSharkDying01;
    blueDyingImages[2] = blueSharkDying02;
    blueDyingImages[3] = blueSharkDying03;
    blueDyingImages[4] = blueSharkDying04;
    blueDyingImages[5] = blueSharkDying05;
    blueDyingImages[6] = blueSharkDying06;

    blueSharkDying = new SharkDeath(blueDyingImages);

    orangeDyingImages = new Bitmap[7];
    orangeDyingImages[0] = orangeSharkDying00;
    orangeDyingImages[1] = orangeSharkDying01;
    orangeDyingImages[2] = orangeSharkDying02;
    orangeDyingImages[3] = orangeSharkDying03;
    orangeDyingImages[4] = orangeSharkDying04;
    orangeDyingImages[5] = orangeSharkDying05;
    orangeDyingImages[6] = orangeSharkDying06;

    orangeSharkDying = new SharkDeath(orangeDyingImages);

  }

  /**
   * Initialize the ball object.
   */
  public void createBall() {
    ball = new Ball(ballBitmap, 0, 0, 0, 0);
  }

  /**
   * Initialize the paddle object.
   */
  public void createPaddle() {
    paddle = new Paddle(mediumPaddle, 160 - mediumPaddle.getWidth() / 2, getHeight() - 50);
  }

  /**
   * Initialize the power up or power down object.
   */
  public void createItem() {
    item = new Item(unknownItem);
  }

  /**
   * Initialize the harpoon object.
   */
  public void createHarpoon() {
    harpoon = new Harpoon(harpoonBitmap);
  }

  /**
   * Initializes a shark object.
   * 
   * @param The number of sharks on the level. Max is 2.
   */
  public void createSharks(int sharks) {

    if (sharks == 1) {
      blueShark =
          new Shark(blueSharkBitmap, getWidth(), BLUE_SHARK_HEIGHT, BLUE_SHARK_VELOCITY, Shark.BLUE);
    }
    else if (sharks == 2) {
      blueShark =
          new Shark(blueSharkBitmap, getWidth(), BLUE_SHARK_HEIGHT, BLUE_SHARK_VELOCITY, Shark.BLUE);
      orangeShark =
          new Shark(orangeSharkBitmap, 0 - orangeSharkBitmap.getWidth(), ORANGE_SHARK_HEIGHT,
              ORANGE_SHARK_VELOCITY, Shark.ORANGE);
    }
  }

  public void createJellyfish() {

    if (jellyfish == 1) {
      jellyfish1 = setJellyfishVariables();
      jellyfishList.add(jellyfish1);
    }
    if (jellyfish == 2) {
      jellyfish1 = setJellyfishVariables();
      jellyfishList.add(jellyfish1);
      jellyfish2 = setJellyfishVariables();
      jellyfishList.add(jellyfish2);
    }
    if (jellyfish == 3) {
      jellyfish1 = setJellyfishVariables();
      jellyfishList.add(jellyfish1);
      jellyfish2 = setJellyfishVariables();
      jellyfishList.add(jellyfish2);
      jellyfish3 = setJellyfishVariables();
      jellyfishList.add(jellyfish3);
    }
    if (jellyfish == 4) {
      jellyfish1 = setJellyfishVariables();
      jellyfishList.add(jellyfish1);
      jellyfish2 = setJellyfishVariables();
      jellyfishList.add(jellyfish2);
      jellyfish3 = setJellyfishVariables();
      jellyfishList.add(jellyfish3);
      jellyfish4 = setJellyfishVariables();
      jellyfishList.add(jellyfish4);
    }
    if (jellyfish == 5) {
      jellyfish1 = setJellyfishVariables();
      jellyfishList.add(jellyfish1);
      jellyfish2 = setJellyfishVariables();
      jellyfishList.add(jellyfish2);
      jellyfish3 = setJellyfishVariables();
      jellyfishList.add(jellyfish3);
      jellyfish4 = setJellyfishVariables();
      jellyfishList.add(jellyfish4);
      jellyfish5 = setJellyfishVariables();
      jellyfishList.add(jellyfish5);
    }
  }

  private Jellyfish setJellyfishVariables() {
    int randomX;
    int jellyfishY = 0 - jellyfishBitmap.getHeight();
    int randomYVelocity;

    randomX = (int) (Math.random() * MainGamePanel.viewWidth);
    if (randomX + jellyfishBitmap.getWidth() > MainGamePanel.viewWidth) {
      randomX = randomX - (randomX + jellyfishBitmap.getWidth() - MainGamePanel.viewWidth);
    }
    randomYVelocity = (int) (Math.random() * 10 + 10);

    long delayTime = ((long) (Math.random() * 5)) * 1000;
    return new Jellyfish(jellyfishBitmap, randomX, jellyfishY, randomYVelocity, delayTime);
  }

  public void createFish() {

    if (fish == 1) {
      fish1 = new Fish(fishBitmap);
      fishList.add(fish1);
    }
    if (fish == 2) {
      fish1 = new Fish(fishBitmap);
      fishList.add(fish1);
      fish2 = new Fish(fishBitmap);
      fishList.add(fish2);
    }

  }

  /**
   * 
   * @param rows - row coordinates of blocks
   * @param columns - column coordinates of blocks
   * @param colors - -2 = bomb, -1 = gray, 1 = green, 2 = yellow, 3 = red
   */
  public void createLevelBlocks(int[] rows, int[] columns, int[] colors) {
    Block block = null;

    for (int i = 0; i < rows.length; i++) {

      if (colors[i] == -2) {
        block =
            new Block(blackBlock, Block.BLACK, redBlock.getWidth() * columns[i]
                + PIXELS_BETWEEN_BLOCKS * columns[i] + 4, redBlock.getHeight()
                * rows[i] + PIXELS_BETWEEN_BLOCKS * rows[i] + 2);
      }
      if (colors[i] == -1) {
        block =
            new Block(grayBlock, Block.GRAY, redBlock.getWidth() * columns[i]
                + PIXELS_BETWEEN_BLOCKS * columns[i] + 4, redBlock.getHeight()
                * rows[i] + PIXELS_BETWEEN_BLOCKS * rows[i] + 2);
      }
      if (colors[i] == 1) {
        block =
            new Block(greenBlock, Block.GREEN, redBlock.getWidth() * columns[i]
                + PIXELS_BETWEEN_BLOCKS * columns[i] + 4, redBlock.getHeight()
                * rows[i] + PIXELS_BETWEEN_BLOCKS * rows[i] + 2);
      }
      if (colors[i] == 2) {
        block =
            new Block(yellowBlock, Block.YELLOW, redBlock.getWidth() * columns[i]
                + PIXELS_BETWEEN_BLOCKS * columns[i] + 4, redBlock.getHeight()
                * rows[i] + PIXELS_BETWEEN_BLOCKS * rows[i] + 2);
      }
      if (colors[i] == 3) {
        block =
            new Block(redBlock, Block.RED, redBlock.getWidth() * columns[i]
                + PIXELS_BETWEEN_BLOCKS * columns[i] + 4, redBlock.getHeight()
                * rows[i] + PIXELS_BETWEEN_BLOCKS * rows[i] + 2);
      }
      blocks.add(block);
      blockEdges.addBlockEdges(block, blockEdgesMap);
    }
  }

  /**
   * Show the result in a pop up dialog.
   * 
   * @param won Whether the player won.
   */
  public void handleResult(boolean won) {

    // stop the running thread
    surfaceDestroyed(getHolder());

    // initialize dialog and its layout
    final Dialog dialog = new Dialog(getContext());
    dialog.setContentView(R.layout.result);
    // map this message to the resource
    TextView message = (TextView) dialog.findViewById(R.id.dialogMessage);

    if (won) {
      preferences = LevelSelection.getPreferences();

      int lastLevel = preferences.getInt("lastLevel", 0);

      if (lastLevel < level) {
        SharedPreferences.Editor ed = preferences.edit();
        ed.putInt("lastLevel", level);
        ed.commit();
      }
      dialog.setTitle("          Level" + level + " Cleared!");

      // calculate the total score
      int levelBonus = 10000;
      // get time bonus if complete within 5 minutes
      long timeBonus = (((300000 - thread.getTimeElapsed()) / 1000) + 1) * 50;
      if (timeBonus < 0) {
        timeBonus = 0;
      }
      int livesBonus = MainThread.getLives() * 1000;
      long totalScore = MainThread.getScore() + levelBonus + timeBonus + livesBonus;

      message.setText(" Original Score:    " + MainThread.getScore() + "\n Level Bonus        "
          + levelBonus + "\n Time Bonus:        " + timeBonus + "\n Lives Bonus:        "
          + livesBonus + "\n Total Score:         " + totalScore + "\n" + "\n  Continue to level "
          + (level + 1) + "? ");
      // Save new score
      MainThread.addScore((int) (levelBonus + timeBonus + livesBonus));

    }
    // if player lost ask whether he/she wants to play again.
    else {
      dialog.setTitle("              Try again?");
    }

    // create yes and no buttons and add onClickListeners to them.
    Button yesButton = (Button) dialog.findViewById(R.id.yesButton);
    Button noButton = (Button) dialog.findViewById(R.id.noButton);
    usernameInput = (EditText) dialog.findViewById(R.id.username);

    preferences = LevelSelection.getPreferences();
    String username = preferences.getString("username", "");
    if ("".equals(username)) {
      usernameInput.setText("Your name");
    }
    else {
      usernameInput.setText(username);
    }

    if (won) {
      // Q: Continue to the next level?
      // if yes go to next level
      yesButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

          saveUserName();
          // When user ends their game,
          // log score into High Score Log
          saveScore();

          dialog.dismiss();

          goToNextLevel = true;

          ((Activity) getContext()).finish();

          // Go to loading page to buy some time before this activity is destroyed.
          // if the next level starts before this activity is destroy Application
          // will freeze. (perhaps it's the emulator.
          Intent intent = new Intent();
          intent.setClassName((Activity) getContext(), LoadingPage.class.getName());
          ((Activity) getContext()).startActivity(intent);
        }
      });
    }
    else {
      // Q: Try again?
      // if yes restart current level.
      yesButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

          saveUserName();
          // When user ends their game,
          // log score into High Score Log
          saveScore();
          dialog.dismiss();

          // restart level
          resetGame();
        }
      });
    }

    // Go back to level selection
    noButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {

        saveUserName();
        // When user ends their game,
        // log score into High Score Log
        saveScore();
        dialog.dismiss();

        // Take user back to Main Menu
        Intent intent = new Intent();
        intent.setClassName((Activity) getContext(), LevelSelection.class.getName());
        ((Activity) getContext()).startActivity(intent);
      }
    });

    // player has to click on one of the button in order to cancel the dialog.
    dialog.setCancelable(false);
    dialog.show();
  }

  /**
   * Save the username in preference.
   */
  public void saveUserName() {
    String inputString = usernameInput.getText().toString();

    // Put new username
    SharedPreferences.Editor ed = preferences.edit();
    ed.putString("username", inputString);
    ed.commit();
  }

  /**
   * Save the score.
   */
  public void saveScore() {
    // When user ends their game,
    // log score into High Score Log
    ScoresDB db = MainThread.getDB();

    SharedPreferences preferences =
        ((Activity) getContext()).getApplicationContext().getSharedPreferences("USER_SETTINGS",
            Context.MODE_WORLD_READABLE);
    String name = preferences.getString("username", null);

    db.addScoreToDB(name, MainThread.getScore(), MainGamePanel.getLevel());
  }

  /**
   * Whether the player wants to go to the next level.
   */
  public boolean goToNextLevel() {
    return goToNextLevel;
  }

  /**
   * Restart the current level.
   */
  public void resetGame() {
    Block.blocksToBreak = 0;
    blocks.clear();
    blockEdgesMap.clear();
    blockEdges.clear();
    int[] levelBlockRows;
    int[] levelBlockColumns;
    int[] levelBlockColors;

    if (level == 1) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 2) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 2, 1, 2, 1, 2, 1, 2, 1, -1, 1, 1, 1, -1, 1, 2, -1, 3, 3, 3, -1, 2, 1, -1, -1,
              -1, -1, -1, 1, 2, 1, 2, 1, 2, 1, 2 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 3) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 3, 3, 3, 2, 3, 3, 3, 3, 2, 2, 1, 2, 2, 3, 2, 2, 1, 1, 1, 2, 2, 3, 2, 2, 1, 2,
              2, 3, 3, 3, 3, 2, 3, 3, 3 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 4) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { 1, -1, -1, -2, -1, -1, 1, -1, 3, 3, 3, 3, 3, -1, -2, 3, 3, 3, 3, 3, -2, -1,
              3, 3, 3, 3, 3, -1, 1, -1, -1, -2, -1, -1, 1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    else if (level == 5) {
      levelBlockRows =
          new int[] { 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
              5, 5, 6, 6, 6, 6, 6, 6, 6 };
      levelBlockColumns =
          new int[] { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5,
              6, 7, 1, 2, 3, 4, 5, 6, 7 };
      levelBlockColors =
          new int[] { -1, -1, -1, 3, -1, -1, -1, -1, 3, -1, 3, -1, 3, -1, -1, 3, -1, 3, -1, 3, -1,
              -1, 3, 3, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1 };
      createLevelBlocks(levelBlockRows, levelBlockColumns, levelBlockColors);
    }
    createPaddle();
    ball.reset();
    item.resetPosition();
    item.removePower(paddle, ball, harpoon, blueShark, orangeShark, fishList, blockEdges);
    if (blueShark != null) {
      blueShark.reset();
    }
    if (orangeShark != null) {
      orangeShark.reset();
    }

    for (Jellyfish jelly : jellyfishList) {
      jelly.reset();
    }

    for (Fish fish : fishList) {
      fish.reset();
    }

    explosion.endExplosion();
    blueEatBall.endEating();
    orangeEatBall.endEating();

    restartThread();
  }

  /**
   * Restarts the game thread.
   */
  public void restartThread() {
    thread = new MainThread(getHolder(), this);
    thread.setStartTime(System.currentTimeMillis());
    thread.setRunning(true);
    MainThread.setLives(5);
    MainThread.setScore(0);
    thread.start();
  }

  /**
   * Start up the thread again.
   */
  public void resumeThread(int lives, int score) {

    long timeElapsed = thread.getTimeElapsed();

    thread = new MainThread(getHolder(), this);
    MainThread.setLives(lives);
    MainThread.setScore(score);
    long currentTime = System.currentTimeMillis();
    long newStartTime = currentTime - timeElapsed;

    thread.setStartTime(newStartTime);

    if (blueSharkKilledAt != -1) {
      newStartTime = currentTime - (pausedTime - blueSharkKilledAt);
      blueShark.setKilledAt(newStartTime);
    }
    if (orangeSharkKilledAt != -1) {
      newStartTime = currentTime - (pausedTime - orangeSharkKilledAt);
      orangeShark.setKilledAt(newStartTime);
    }
    for (Jellyfish jelly : jellyfishList) {
      jelly.setLastUpdateTime(-1);
      jelly.resume();
    }
    
    for (Fish fish : fishList) {
      fish.setLastUpdateTime(-1);
      fish.resume();
    }

    thread.setRunning(true);
    thread.start();
  }

  /**
   * Return the current level.
   * 
   * @return The level number
   */
  public static int getLevel() {
    return level;
  }

  /**
   * Return the current list of blocks. Called by activities for game state storage.
   * 
   * @return The list of blocks.
   */
  public List<Block> getBlocks() {
    return blocks;
  }

  /**
   * Set the list of blocks. Called by Activities to resume game state.
   * 
   * @param blocks
   */
  public void setBlocks(List<Block> blocks) {
    this.blocks = blocks;
  }

  /**
   * Return the ball object. Calld by activities for game state storage.
   * 
   * @return The ball.
   */
  public Ball getBall() {
    return ball;
  }

  /**
   * Set the ball. Called by Activities to resume game state.
   * 
   * @param ball
   */
  public void setBall(Ball ball) {
    this.ball = ball;
  }

  /**
   * Return the Paddle object. Calld by activities for game state storage.
   * 
   * @return The Paddle.
   */
  public Paddle getPaddle() {
    return paddle;
  }

  /**
   * Set the paddle. Called by Activities to resume game state.
   * 
   * @param paddle The paddle.
   */
  public void setPaddle(Paddle paddle) {
    this.paddle = paddle;
  }

  /**
   * Return the blue shark object. Calld by activities for game state storage.
   * 
   * @return The blue shark.
   */
  public Shark getBlueShark() {
    return blueShark;
  }

  /**
   * Return the orange shark object. Calld by activities for game state storage.
   * 
   * @return The orange shark.
   */
  public Shark getOrangeShark() {
    return orangeShark;
  }

  /**
   * Set the blue shark. Called by Activities to resume game state.
   * 
   * @param blueShark The blue shark.
   */
  public void setBlueShark(Shark blueShark) {
    this.blueShark = blueShark;
  }

  /**
   * Set the orange shark. Called by Activities to resume game state.
   * 
   * @param orangeShark The orange shark.
   */
  public void setOrangeShark(Shark orangeShark) {
    this.orangeShark = orangeShark;
  }

  /**
   * Return the item object. Calld by activities for game state storage.
   * 
   * @return The item.
   */
  public Item getItem() {
    return item;
  }

  /**
   * Set the item. Called by Activities to resume game state.
   * 
   * @param item The item.
   */
  public void setItem(Item item) {
    this.item = item;
  }

  /**
   * Return the Harpoon object. Calld by activities for game state storage.
   * 
   * @return The harpoon.
   */
  public Harpoon getHarpoon() {
    return harpoon;
  }

  /**
   * Set the harpoon. Called by Activities to resume game state.
   * 
   * @param item The item.
   */
  public void setHarpoon(Harpoon harpoon) {
    this.harpoon = harpoon;
  }

  public static void setBlueKilledAt(long killed) {
    blueSharkKilledAt = killed;
  }

  public static void setOrangeKilledAt(long killed) {
    orangeSharkKilledAt = killed;
  }

  /**
   * Returns the main thread.
   * 
   * @return The main thread.
   */
  public MainThread getMainThread() {
    return thread;
  }
}
